﻿// -------------------------------------------------------------------------
//    @FileName         :    NFQuestPart.cpp
//    @Author           :    gaoyi
//    @Date             :    2025/1/13
//    @Email            :    445267987@qq.com
//    @Module           :    NFQuestPart
//
// -------------------------------------------------------------------------

#include "NFQuestPart.h"

#include <NFEventDisp.h>
#include <NFPlayer.h>
#include <NFServiceQuest.h>
#include <proto_log.pb.h>
#include <DescStore/LoopQuestDesc.h>
#include <DescStore/QuestDesc.h>
#include <DescStore/RoleInitInfoDesc.h>

#include "proto_db.pb.h"

NFQuestPart::NFQuestPart()
{
    if (EN_OBJ_MODE_INIT == NFShmMgr::Instance()->GetCreateMode())
    {
        CreateInit();
    }
    else
    {
        ResumeInit();
    }
}

NFQuestPart::~NFQuestPart()
{
}

int NFQuestPart::CreateInit()
{
    return 0;
}

int NFQuestPart::ResumeInit()
{
    return 0;
}

int NFQuestPart::LoadFromDB(const proto_ff::tbRoleDetail* pDBData)
{
    auto& data = pDBData->role_play_data().quest_data();
    m_stData.FromPb(data);
    m_finished_quest.Set(data.finished_quest());
    m_finished_achieve.Set(data.finished_achieve());
    m_achieve_reward.Set(data.achieve_reward());
    return 0;
}

int NFQuestPart::InitConfig(proto_ff::tbRoleDetail* pDbData, const RoleOne& stRoleOne)
{
    return 0;
}

int NFQuestPart::SaveDB(proto_ff::tbRoleDetail* pDBData)
{
    auto pData = pDBData->mutable_role_play_data()->mutable_quest_data();
    m_stData.ToPb(pData);
    m_finished_quest.Get(*pData->mutable_finished_quest());
    m_finished_achieve.Get(*pData->mutable_finished_achieve());
    m_achieve_reward.Get(*pData->mutable_achieve_reward());

    return 0;
}

int NFQuestPart::MakePlayerDataCS(proto_ff::Proto_CSGetRoleRsp* pCSGetRoleRsp)
{
    auto pQuestData = pCSGetRoleRsp->mutable_quest_data();
    for (int i = 0; i < (int)QuestDesc::Instance()->GetResNum(); i++)
    {
        auto pDesc = QuestDesc::Instance()->GetDescByIndex(i);
        if (pDesc && pDesc->id > 0 && IsFinished(pDesc->id))
        {
            pQuestData->add_completed_list(pDesc->id);
        }
    }

    for (auto iter = m_stData.accepted_list.list_begin(); iter != m_stData.accepted_list.list_end(); ++iter)
    {
        auto pDesc = QuestDesc::Instance()->GetDesc(iter->second.quest_id);
        if (!pDesc) continue;

        if (pDesc->id > 0)
        {
            iter->second.ToPb(pQuestData->add_accepted_list());
        }
    }

    for (auto iter = m_stData.loop_list.list_begin(); iter != m_stData.loop_list.list_end(); ++iter)
    {
        auto pLoopDesc = LoopQuestDesc::Instance()->GetDesc(iter->second.loop_id);
        if (!pLoopDesc)
        {
            LOGSVR_WARN("quest loop removed: " << iter->second.loop_id);
            continue;
        }

        if (iter->second.accepted_time == 0) continue;

        iter->second.ToPb(pQuestData->add_questloop_list());
    }
    return 0;
}

int NFQuestPart::MakeCityPlayerData(proto_ff::CityRoleInfo* pGCCityRoleInfo)
{
    CHECK_NULL(0, pGCCityRoleInfo);
    MakeCityPlayerData(pGCCityRoleInfo->mutable_quest_data());
    pGCCityRoleInfo->set_title2_id(GetTitle2());
    return 0;
}

int NFQuestPart::MakeCityPlayerData(proto_ff::CityRoleQuestData* pQuestData)
{
    CHECK_NULL(0, pQuestData);
    for (auto iter = m_stData.accepted_list.list_begin(); iter != m_stData.accepted_list.list_end(); ++iter)
    {
        iter->second.ToPb(pQuestData->add_accepted_list());
    }
    return 0;
}

int NFQuestPart::OnRegister()
{
    auto pPlayer = GetPlayer();
    CHECK_NULL(0, pPlayer);

    bool bFirstQuest = false;
    for (int i = 0; i < (int)RoleInitInfoDesc::Instance()->GetResNum(); ++i)
    {
        auto pRoleInitInfo = RoleInitInfoDesc::Instance()->GetDescByIndex(i);
        CHECK_NULL(0, pRoleInitInfo);

        if (pRoleInitInfo->type == proto_ff::EN_ROLE_INIT_TYPE_QUEST)
        {
            NFServiceQuest::Accept(pPlayer, pRoleInitInfo->ext_id, false, true);
            bFirstQuest = true;
        }
    }

    if (bFirstQuest)
    {
        NFEventDisp::OnSessionLogCheckPoint(pPlayer->GetClientSession(), proto_ff::CHECK_POINT_14);
    }
    return 0;
}

QuestNode* NFQuestPart::GetQuestNode(int iQuestID)
{
    auto iter = m_stData.accepted_list.find(iQuestID);
    if (iter != m_stData.accepted_list.end())
    {
        return &iter->second;
    }
    return nullptr;
}

QuestNode* NFQuestPart::AddQuestNode(int iQuestID)
{
    QuestNode* pNode = GetQuestNode(iQuestID);
    if (pNode == nullptr)
    {
        if (m_stData.accepted_list.size() < m_stData.accepted_list.max_size())
        {
            pNode = &m_stData.accepted_list[iQuestID];
            pNode->quest_id = iQuestID;
            MarkDirty();
        }
    }
    return pNode;
}

int NFQuestPart::DelQuestNode(int iQuestID)
{
    m_stData.accepted_list.erase(iQuestID);
    MarkDirty();
    return 0;
}

LoopQuest* NFQuestPart::GetLoopQuest(int iLoopID)
{
    auto iter = m_stData.loop_list.find(iLoopID);
    if (iter != m_stData.loop_list.end())
    {
        return &iter->second;
    }
    return nullptr;
}

LoopQuest* NFQuestPart::AddLoopQuest(int iLoopID)
{
    auto pLoopQuest = GetLoopQuest(iLoopID);
    if (pLoopQuest)
    {
        LOG_ERR(0, -1, "iLoopID:{} exist", iLoopID);
        return pLoopQuest;
    }

    if (m_stData.loop_list.size() < m_stData.loop_list.max_size())
    {
        pLoopQuest = &m_stData.loop_list[iLoopID];
        pLoopQuest->loop_id = iLoopID;
        pLoopQuest->crit_times = 1;
        pLoopQuest->node_times = 0;
        pLoopQuest->accepted_time = NF_ADJUST_TIMENOW();
        pLoopQuest->node_index = 0;

        MarkDirty();
    }

    return pLoopQuest;
}

int NFQuestPart::DelLoopQuest(int iLoopID)
{
    auto pLoopQuest = GetLoopQuest(iLoopID);
    if (pLoopQuest == NULL)
    {
        LOG_ERR(0, -1, "iLoopID:{} not exist", iLoopID);
        return -1;
    }

    m_stData.loop_list.erase(iLoopID);
    MarkDirty();
    return 0;
}

LoopQuestFinishedNode* NFQuestPart::GetLoopQuestHis(int iID)
{
    auto iter = m_stData.loop_quest_nodes_list.find(iID);
    if (iter != m_stData.loop_quest_nodes_list.end())
    {
        return &iter->second;
    }

    if (m_stData.loop_quest_nodes_list.size() >= m_stData.loop_quest_nodes_list.max_size())
    {
        LOG_ERR(0, -1, "m_stData.loop_quest_nodes_list Space Not Enough");
        return nullptr;
    }

    auto pNode = &m_stData.loop_quest_nodes_list[iID];
    pNode->quest_id = iID;
    pNode->last_finished_time = 0;
    pNode->times_in_day = 0;
    return pNode;
}

void NFQuestPart::FinishQuest(int iQuestID)
{
    m_finished_quest.SetBit(iQuestID);
    MarkDirty();
}

QuestFinishCount* NFQuestPart::FindQuestCount(int iQuestID)
{
    auto iter = m_stData.quest_finish_count.find(iQuestID);
    if (iter != m_stData.quest_finish_count.end())
    {
        return &iter->second;
    }
    return nullptr;
}

QuestFinishCount* NFQuestPart::InsertQuestCount(int iQuestID)
{
    if (m_stData.quest_finish_count.full())
    {
        CHECK_ERR_RE_NULL(m_roleId, -1, "QuestFinishCount Full");
    }

    auto pData = &m_stData.quest_finish_count[iQuestID];
    CHECK_NULL_RE_NULL(m_roleId, pData, "QuestFinishCount Insert Failed");
    pData->quest_id = iQuestID;
    pData->count = 0;
    MarkDirty();
    return pData;
}

int NFQuestPart::GetQuestCount(int iQuestID)
{
    auto pFinishCount = FindQuestCount(iQuestID);
    if (pFinishCount)
    {
        return pFinishCount->count;
    }
    return 0;
}

int NFQuestPart::AddQuestCount(int iQuestID)
{
    auto pFinishCount = FindQuestCount(iQuestID);
    if (pFinishCount == nullptr)
    {
        pFinishCount = InsertQuestCount(iQuestID);
    }
    CHECK_NULL(m_roleId, pFinishCount);
    pFinishCount->count++;
    MarkDirty();
    return 0;
}
